#!/bin/sh
#                    R T W I Z A R D . T C L
# BRL-CAD
#
# Copyright (c) 2006-2025 United States Government as represented by
# the U.S. Army Research Laboratory.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# version 2.1 as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this file; see the file named COPYING for more
# information.
#
###
#
# Start-up script for both the command line and graphical modes of
# rtwizard
#

if {![info exists ::RtWizard::wizard_state(pid_filename)]} {
    if {$::tcl_platform(platform) == "windows"} {
	set ::RtWizard::wizard_state(pid_filename) "NUL"
    } else {
	set ::RtWizard::wizard_state(pid_filename) "/dev/null"
    }
}

if {![info exists ::RtWizard::wizard_state(log_file)]} {
    if {$::tcl_platform(platform) == "windows"} {
	set ::RtWizard::wizard_state(log_file) "NUL"
    } else {
	set ::RtWizard::wizard_state(log_file) "/dev/null"
    }
}

# Geometry Database
if {![info exists ::RtWizard::wizard_state(dbFile)]} { set ::RtWizard::wizard_state(dbFile) "" }
# Initial orientation
if {![info exists ::RtWizard::wizard_state(init_azimuth)]} { set ::RtWizard::wizard_state(init_azimuth) 35 }
if {![info exists ::RtWizard::wizard_state(init_elevation)]} { set ::RtWizard::wizard_state(init_elevation) 25 }
if {![info exists ::RtWizard::wizard_state(init_twist)]} { set ::RtWizard::wizard_state(init_twist) 0 }
# Initial zoom
if {![info exists ::RtWizard::wizard_state(zoom)]} { set ::RtWizard::wizard_state(zoom) 1 }
# Initial perspective
if {![info exists ::RtWizard::wizard_state(perspective)]} { set ::RtWizard::wizard_state(perspective) 0 }
# Background color
if {![info exists ::RtWizard::wizard_state(bg_color)]} { set ::RtWizard::wizard_state(bg_color) {255 255 255} }
# Edge lines color
if {![info exists ::RtWizard::wizard_state(e_color)]} { set ::RtWizard::wizard_state(e_color) {0 0 0} }
# Edge not-lines color
if {![info exists ::RtWizard::wizard_state(ne_color)]} { set ::RtWizard::wizard_state(ne_color) {0 0 0} }
# Occlusion mode
if {![info exists ::RtWizard::wizard_state(occmode)]} { set ::RtWizard::wizard_state(occmode) 1 }
# Ghost intensity
if {![info exists ::RtWizard::wizard_state(ghost_intensity)]} { set ::RtWizard::wizard_state(ghost_intensity) 6 }
# Pix width
if {![info exists ::RtWizard::wizard_state(width)]} { set ::RtWizard::wizard_state(width) 512 }
# Pix height (number of scan lines)
if {![info exists ::RtWizard::wizard_state(scanlines)]} { set ::RtWizard::wizard_state(scanlines) 512 }

# Load the package that lets us output images
package require cadwidgets::RtImage

# Set verbosity if not already set
if {![info exists ::RtWizard::wizard_state(verbose)]} {
    set ::RtWizard::wizard_state(verbose) 0
}

# Set benchmark mode, if not already set
if {[info exists ::benchmark_mode]} {
    set ::benchmark_mode "-B"
} else {
    set ::benchmark_mode ""
}

# If we're launching without enough arguments to fully specify an rtwizard
# run or a gui run has been specifically requested, go graphical
if {[info exists ::use_gui]} {
   # Load the actual Raytrace Wizard GUI
   package require RaytraceWizard
   if {[info exists argv]} {exit}
} else {

   if {![info exists ::RtWizard::wizard_state(output_filename)] && ![info exists ::RtWizard::wizard_state(fbserv_port)] && ![info exists ::RtWizard::wizard_state(fbserv_device)]} {
     set ::RtWizard::wizard_state(output_filename) rtwizard.pix
     if {![file exists $::RtWizard::wizard_state(output_filename)]} {
	puts "Warning - no output file or framebuffer specified - using file rtwizard.pix for output."
     }
   }
   if {[info exists ::RtWizard::wizard_state(output_filename)]} {
     if {[file exists $::RtWizard::wizard_state(output_filename)]} {
	puts "Error - cannot create output file, $::RtWizard::wizard_state(output_filename) already exists."
	if {[info exists argv]} {exit}
     }
   }

   # Get an in-memory framebuffer, if we don't already have a type set
   if {![info exists ::RtWizard::wizard_state(fbserv_device)]} {
      set ::RtWizard::wizard_state(fbserv_device) /dev/mem
      set fbtype_specified 0
   } else {
      set fbtype_specified 1
   }

   # We need a port number for the fbserv.
   if {![info exists ::RtWizard::wizard_state(fbserv_port)]} {
      set ::RtWizard::wizard_state(fbserv_port) 0
      set port_number_specified 0
   } else {
      set port_number_specified 1
   }
   # Check whether the framebuffer already exists.  If it does, and if
   # it was specified on the command line, go with it.
   if { [catch {exec [file join [bu_dir bin] fblabel] -F $::RtWizard::wizard_state(fbserv_port) 1 1 " "} error ] && $error == 12} {
      catch {exec [file join [bu_dir bin] fbserv] -w $::RtWizard::wizard_state(width) -n $::RtWizard::wizard_state(scanlines) $::RtWizard::wizard_state(fbserv_port) $::RtWizard::wizard_state(fbserv_device) &} pid
      if {[info exists pid]} {
	set fbserv_pid $pid
	# Wait a few milliseconds to make sure fbserv has completed its work and is available
	while { [catch {exec [file join [bu_dir bin] fblabel] -F $::RtWizard::wizard_state(fbserv_port) 1 1 " "} error] && $error == 12} {after 300}
      } else {
	if {$::RtWizard::wizard_state(verbose)} {puts "fbserv port $::RtWizard::wizard_state(fbserv_port) failed!"}
	incr ::RtWizard::wizard_state(fbserv_port)
      }
   }

   # If we didn't have a pre-specified port number and the default didn't work, start counting up
   if { ! $port_number_specified && ! [info exists fbserv_pid] } {
       incr ::RtWizard::wizard_state(fbserv_port)
       while { ! [catch {exec [file join [bu_dir bin] fbclear] -F $::RtWizard::wizard_state(fbserv_port) } error ] } {
	     if {$::RtWizard::wizard_state(verbose)} {puts "fbserv port $::RtWizard::wizard_state(fbserv_port) is already in use."}
	     incr ::RtWizard::wizard_state(fbserv_port)
       }
      catch {exec [file join [bu_dir bin] fbserv] -w $::RtWizard::wizard_state(width) -n $::RtWizard::wizard_state(scanlines) $::RtWizard::wizard_state(fbserv_port) $::RtWizard::wizard_state(fbserv_device) &} pid
      set fbserv_pid $pid
      # Wait a few milliseconds to make sure fbserv has completed its work and is available
      while { [catch {exec [file join [bu_dir bin] fblabel] -F $::RtWizard::wizard_state(fbserv_port) 1 1 " "} error] && $error == 12 } {after 300}
   }

   # Either we're using a specified view model, or we're deducing one based on user options
   if {[info exists ::RtWizard::wizard_state(viewsize)] && [info exists ::RtWizard::wizard_state(orientation)] && [info exists ::RtWizard::wizard_state(eye_pt)]} {
     set viewsize $::RtWizard::wizard_state(viewsize)
     set orientation [split $::RtWizard::wizard_state(orientation) " "]
     set eye_pt [split $::RtWizard::wizard_state(eye_pt) " "]
     if {[info exists ::have_azimuth]} {puts "Warning - view model explicitly set - ignoring azimuth option"}
     if {[info exists ::have_elevation]} {puts "Warning - view model explicitly set - ignoring elevation option"}
     if {[info exists ::have_twist]} {puts "Warning - view model explicitly set - ignoring twist option"}
     if {[info exists ::have_zoom]} {puts "Warning - view model explicitly set - ignoring zoom option"}
     if {[info exists ::have_center]} {puts "Warning - view model explicitly set - ignoring center option"}

   } else {
     if {[info exists ::RtWizard::wizard_state(viewsize)] || [info exists ::RtWizard::wizard_state(orientation)] || [info exists ::RtWizard::wizard_state(eye_pt)]} {
	if {! [info exists ::have_viewsize]} {puts "Error - when specifying view model directly, need viewsize"}
	if {! [info exists ::have_orientation]} {puts "Error - when specifying view model directly, need orientation"}
	if {! [info exists ::have_eye_pt]} {puts "Error - when specifying view model directly, need eye_pt"}
	if {[info exists argv]} {exit}
     }
     set db [go_open db db $::RtWizard::wizard_state(dbFile)]
     db new_view v1 nu

     if {[llength $::RtWizard::wizard_state(color_objlist)]} {
	foreach item $::RtWizard::wizard_state(color_objlist) {
	  db draw $item
	}
     }
     if {[llength $::RtWizard::wizard_state(line_objlist)]} {
	foreach item $::RtWizard::wizard_state(line_objlist) {
	  db draw $item
	}
     }
     if {[llength $::RtWizard::wizard_state(ghost_objlist)]} {
	foreach item $::RtWizard::wizard_state(ghost_objlist) {
	  db draw $item
	}
     }

     db autoview v1
     db aet v1 $::RtWizard::wizard_state(init_azimuth) $::RtWizard::wizard_state(init_elevation) $::RtWizard::wizard_state(init_twist)
     db zoom v1 $::RtWizard::wizard_state(zoom)
     db perspective v1 $::RtWizard::wizard_state(perspective)
     if {[info exists ::RtWizard::wizard_state(x_center)] && [info exists ::RtWizard::wizard_state(y_center)] && [info exists ::RtWizard::wizard_state(z_center)]} {
	db center v1 $::RtWizard::wizard_state(x_center) $::RtWizard::wizard_state(y_center) $::RtWizard::wizard_state(z_center)
     }
     set view_info [regsub -all ";" [db get_eyemodel v1] ""]
     set vdata [split $view_info "\n"]
     set viewsize [lindex [lindex $vdata 0] 1]
     set orientation [lrange [lindex $vdata 1] 1 end]
     set eye_pt [lrange [lindex $vdata 2] 1 end]
   }

   # populate a dictionary to pass to rtimage
   set rtimage_dict [dict create \
       _dbfile $::RtWizard::wizard_state(dbFile) \
       _port $::RtWizard::wizard_state(fbserv_port) \
       _w $::RtWizard::wizard_state(width) \
       _n $::RtWizard::wizard_state(scanlines) \
       _viewsize $viewsize \
       _orientation $orientation \
       _eye_pt $eye_pt \
       _perspective $::RtWizard::wizard_state(perspective) \
       _bgcolor $::RtWizard::wizard_state(bg_color) \
       _ecolor $::RtWizard::wizard_state(e_color) \
       _necolor $::RtWizard::wizard_state(ne_color)\
       _occmode $::RtWizard::wizard_state(occmode) \
       _gamma $::RtWizard::wizard_state(ghost_intensity) \
       _color_objects  $::RtWizard::wizard_state(color_objlist) \
       _ghost_objects  $::RtWizard::wizard_state(ghost_objlist) \
       _edge_objects  $::RtWizard::wizard_state(line_objlist) \
       _benchmark_mode  $::benchmark_mode \
       _log_file  $::RtWizard::wizard_state(log_file) \
       _pid_filename $::RtWizard::wizard_state(pid_filename)
       ]


    ::cadwidgets::rtimage $rtimage_dict

   if {[info exists ::RtWizard::wizard_state(output_filename)]} {
      set output_generated 0
      if {[file extension $::RtWizard::wizard_state(output_filename)] == ".png"} {
	 exec [file join [bu_dir bin] fb-png] -w $::RtWizard::wizard_state(width) -n $::RtWizard::wizard_state(scanlines) -F $::RtWizard::wizard_state(fbserv_port) $::RtWizard::wizard_state(output_filename)
	 set output_generated 1
      }
      if {!$output_generated} {
	 exec [file join [bu_dir bin] fb-pix] -w $::RtWizard::wizard_state(width) -n $::RtWizard::wizard_state(scanlines) -F $::RtWizard::wizard_state(fbserv_port) $::RtWizard::wizard_state(output_filename)
	 set output_generated 1
      }

   }


   if {$::RtWizard::wizard_state(fbserv_device) == "/dev/mem"} {
       if {[info exists fbserv_pid]} {
	  if {$::tcl_platform(platform) == "windows"} {
	      set kill_cmd [auto_execok taskkill]
	      set kill_args [list $kill_cmd "/F" "/PID" $fbserv_pid]
	  } else {
	      set kill_cmd [auto_execok kill]
	      set kill_args [list $kill_cmd $fbserv_pid]
	  }
	  if {$kill_cmd != ""} {
	      exec {*}$kill_args
	  }
      }
   }
}

# Local Variables:
# mode: sh
# tab-width: 8
# sh-indentation: 4
# sh-basic-offset: 4
# indent-tabs-mode: t
# End:
# ex: shiftwidth=4 tabstop=8
